import parole
from parole.colornames import colors
from parole.display import interpolateRGB
import pygame, random
from pprint import pprint

import sim, interface
from util import *

COLS, ROWS = 150, 60
roadY = 27
roadHeight = 5

# TODO: give player +8 perception while in town

class HouseFloor(sim.Floor):
    pass

def makeNewTown():
    mbox = interface.messageBox('Welcome to the village of Anoiktos...')
    parole.display.update()

    # Create map 
    map = parole.map.Map2D('newtown', (COLS, ROWS))
    grass = GrassAreaGenerator()
    grass.apply(map)

    # road down the middle
    road = RoadAreaGenerator()
    roadRect = pygame.Rect((0, roadY), (COLS, roadHeight))
    road.apply(map, roadRect)

    # town gate
    gate = parole.resource.getObject('scripts/rooms/town_gate.py',
            'roomClass')((0,0))
    gate.rect = pygame.Rect((24, roadY-2), gate.size)
    gate.apply(map)

    # slap some buildings down
    rg = roomGenerator()
    layRooms(map, 30, 0, COLS, ROWS, rg, True)
    layRooms(map, 30, 32, COLS, ROWS, rg, False)
    
    # and the mine entrance
    mineEntrance = MineEntranceGenerator()
    entranceRect = pygame.Rect((5,2), (18,11))
    mineEntrance.apply(map, entranceRect)
    layPathsFromDoorsToRoad(map, entranceRect, True)

    # it's day time
    map.setAmbientLight((255,255,255), 0.8)
    map.update()

    parole.display.scene.remove(mbox)
    parole.display.update()

    # return map, player starting pos, and dstairs
    return map, (2,29), (8, 4) 

def layRooms(map, x, y, COLS, ROWS, rg, aboveRoad):
    while x < COLS:
        parole.debug("New room requested at (%d,%d)...", x, y)
        roomName = rg.next()
        roomClass = parole.resource.getObject('scripts/rooms/%s.py' % roomName,
                'roomClass')
        
        room = roomClass((0,0))
        roomX, roomY = max(0, x + random.randint(1, 2)),\
                       max(0, y + random.randint(1, 3))
        if roomX + room.size[0] >= COLS or y >= ROWS:
            x += 1
            continue
        x = roomX + room.size[0]
        y = y

        if aboveRoad:
            room.pos = (roomX, roadY - room.size[1] - random.randint(1, 3))
        else:
            room.pos = (roomX, roomY)
        room.rect = pygame.Rect(room.pos, room.size)
        parole.debug('Placing town building %r at %r' % (roomName, room.pos))
        room.apply(map)

        # lay paths to the road
        layPathsFromDoorsToRoad(map, room.rect, aboveRoad)

def layPathsFromDoorsToRoad(map, rect, aboveRoad):
    if aboveRoad:
        roadJoinPos = (rect.centerx, roadY)
    else:
        roadJoinPos = (rect.centerx, roadY + roadHeight)
    for tile in map.iterTiles(rect=rect):
        foundDoor = False
        for obj in tile:
            if isinstance(obj, sim.Door):
                foundDoor = True
                break
        if foundDoor:
            layPath(map, (tile.col, tile.row), roadJoinPos, skipStart=True)

def layPath(map, start, goal, skipStart=False, skipGoal=False):
    baseRoadR, baseRoadG, baseRoadB = colors['SaddleBrown']
    try:
        path = map.getAStarPath(start, goal,
                neighborFunc=map.cardinalNeighborsOf)
    except parole.map.NoAStarPathError:
        return

    for pos in path:
        if skipStart and pos == start:
            continue
        if skipGoal and pos == goal:
            continue
        tile = map[pos]
        floors = []
        for obj in tile:
            if isinstance(obj, sim.Floor):
                floors.append(obj)
        for floor in floors:
            tile.remove(floor)
        n = random.randint(3,9)
        tile.add(sim.Floor('dirt path', -3,
                    parole.map.AsciiTile(random.choice([' ']*5 + ['.',"'"]), 
                        colors['SaddleBrown'],
                        bg_rgb=(baseRoadR-(n)*5+random.randint(00,00),
                                baseRoadG-(n)*5+random.randint(00,00),
                                baseRoadB-(n)*5+random.randint(00,00)))))
                

def roomGenerator():
    yield 'town_inn'
    yield 'town_cemetary'
    yield 'town_library'
    while 1:
        yield 'town_house'

class GrassAreaGenerator(parole.map.CellularAutomataGenerator):
    """
    Generates smoothly interpolated fields of grass/sand. Used by the apply()
    method.
    """
    def __init__(self, sandColor=colors['DarkGreen'],
            grassColor=colors['Olive']):
        grassGenerator = \
            lambda bg_rgb: parole.map.MapObjectGenerator("grassGenerator",
                lambda: sim.Floor('grass', -200, 
                    parole.map.AsciiTile(' ',#random.choice([' ']*3 + [',',';',"'", '"']),
                    (0,0,0),#(random.randint(0,64),random.randint(96,160),random.randint(0,64)),
                    bg_rgb=bg_rgb), massNoun=True))
        grassConditions = {
            0: grassGenerator(interpolateRGB(sandColor, grassColor, 0.0)),
            1: grassGenerator(interpolateRGB(sandColor, grassColor, 0.1)),
            2: grassGenerator(interpolateRGB(sandColor, grassColor, 0.2)),
            3: grassGenerator(interpolateRGB(sandColor, grassColor, 0.3)),
            4: grassGenerator(interpolateRGB(sandColor, grassColor, 0.4)),
            5: grassGenerator(interpolateRGB(sandColor, grassColor, 0.5)),
            6: grassGenerator(interpolateRGB(sandColor, grassColor, 0.6)),
            7: grassGenerator(interpolateRGB(sandColor, grassColor, 0.8)),
            8: grassGenerator(interpolateRGB(sandColor, grassColor, 0.9)),
            9: grassGenerator(interpolateRGB(sandColor, grassColor, 1.0))
        }
        super(GrassAreaGenerator, self).__init__("grassAreaGenerator", 0.90,
                grassConditions, seedEdges=True)

class RoadAreaGenerator(parole.map.CellularAutomataGenerator):
    def __init__(self):
        # Road (cellular automata)
        baseRoadR, baseRoadG, baseRoadB = colors['SaddleBrown']
        roadGenerator = \
            lambda n: parole.map.MapObjectGenerator("roadGenerator",
                lambda: sim.Floor('dirt road', -3,
                    parole.map.AsciiTile(random.choice([' ']*5 + ['.',"'"]), 
                        colors['SaddleBrown'],
                        bg_rgb=(baseRoadR-(n)*5+random.randint(00,00),
                                baseRoadG-(n)*5+random.randint(00,00),
                                baseRoadB-(n)*5+random.randint(00,00)))))
        roadConditions = {
            3: roadGenerator(3),
            4: roadGenerator(4),
            5: roadGenerator(5),
            6: roadGenerator(6),
            7: roadGenerator(7),
            8: roadGenerator(8),
            9: roadGenerator(9)
        }
        super(RoadAreaGenerator, self).__init__("roadGenerator",
                0.50, roadConditions, seedEdges=True, clearFirst=True)

class MineEntranceGenerator(parole.map.TemplateGenerator):
    def __init__(self):
        # Generators for the mine entrance
        stoneGenerator = parole.map.MapObjectGenerator("stoneGenerator", 
                lambda: sim.Obj('stone outcropping', 100, 
                    parole.map.AsciiTile(' ',
                    (0,0,0),
                    bg_rgb=interpolateRGB(colors['Gray'], colors['Silver'], max(0.0,
                        min(1.0, random.normalvariate(0.33, 0.3))))), blockLOS=True,
                    blockMove=True), clearFirst=True)
        mineshaftGenerator = parole.map.MapObjectGenerator("mineshaftGenerator", 
                lambda: sim.Obj('gaping mineshaft into the earth, charred and '
                    'stained with yellow', 100,
                    parole.map.AsciiTile('>', 
                        colors['Yellow'],
                        bg_rgb=(0,0,0)
                    )), clearFirst=True)
        hatchGenerator = parole.map.MapObjectGenerator("hatchGenerator", 
                lambda: sim.Door('solid chondrite hatch', 100,
                    parole.map.AsciiTile('/', colors['Silver'],
                        bg_rgb=colors['Gray']),parole.map.AsciiTile('+',
                            colors['Silver'], bg_rgb=colors['Gray'])))
        dirtGenerator = parole.map.MapObjectGenerator("dirtGenerator", 
                lambda: sim.Floor('barren earth', 100,
                    parole.map.AsciiTile('.', (244 + random.randint(-25,25),
                                               164 + random.randint(-12,12),
                                               96 + random.randint(-8,8)),
                        bg_rgb=(205 + random.randint(-10,10),
                                133 + random.randint(-7,7),
                                63 + random.randint(-4,4))
                        ), massNoun=True), clearFirst=True)
        signGenerator = parole.map.MapObjectGenerator("signGenerator", 
                lambda: sim.Obj('painted wooden sign that reads "MINES CLOSED,'\
                    ' ENTER AT YOUR OWN RISK"', 100,
                    parole.map.AsciiTile('=', 
                        colors['Yellow'],
                        bg_rgb=colors['SaddleBrown']
                    )), clearFirst=False)

        # Entrance to the mines
        entranceTemplate = \
"""
  ###   ##
 ##.##   ##     #
 #.>.### #     # 
 ##...### #     ##
##...### #     ##
 ##...### #     ##
###...###  ##
 ###..##   ###
  ##.#####  ###
   #+##    ##
     =
"""[1:]
        entranceLegend = {
                    '#': stoneGenerator,
                    '>': mineshaftGenerator,
                    '.': dirtGenerator,
                    '+': hatchGenerator,
                    '=': signGenerator,
                }
        super(MineEntranceGenerator, self).__init__("entranceGenerator",
                entranceTemplate, entranceLegend)

